package ltd.bugs.cute.urm.interceptor;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import ltd.bugs.cute.api.http.statuscode.CommonStatusCode;
import ltd.bugs.cute.common.session.SecuritySession;
import ltd.bugs.cute.urm.annotation.UrmAPI;
import ltd.bugs.cute.urm.helper.PermHelper;
import ltd.bugs.cute.urm.model.Menu;
import ltd.bugs.cute.urm.model.Role;
import ltd.bugs.cute.urm.model.User;
import ltd.bugs.cute.urm.service.MenuService;
import ltd.bugs.cute.urm.service.RoleService;
import ltd.bugs.cute.web.exception.BizException;

/**
 * 权限身份证拦截器
 * 
 * @author zhengzhq
 *
 */
@Component
public class UrmAccessInterceptor implements HandlerInterceptor {


  private static Logger logger = LoggerFactory.getLogger(UrmAccessInterceptor.class);
  private static AntPathMatcher pathMatcher = new AntPathMatcher();

  @Autowired
  private PermHelper permHelper;
  @Autowired
  private RoleService roleService;
  @Autowired
  private MenuService menuService;

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    if (!(handler instanceof HandlerMethod)) {
      return true;
    }

    // 是否登录后才能访问该url
    boolean isNeedLogin = true;
    // 是否需要校验菜单权限
    boolean isCheckMenuPerm = true;
    // 校验管理员
    boolean isCheckAdmin = false;
    // 获取注解上的class，如果没有标注AdminAPI，默认校验权限以及登录情况；有标注以实际情况为准
    HandlerMethod handlerMethod = (HandlerMethod) handler;
    if (handlerMethod.getMethod().isAnnotationPresent(UrmAPI.class)) {
      UrmAPI urmAPI = handlerMethod.getMethod().getAnnotation(UrmAPI.class);
      isNeedLogin = urmAPI.needLogin();
      isCheckMenuPerm = urmAPI.checkMenuPerm();
      isCheckAdmin = urmAPI.checkAdmin();
    }

    // 需要登录
    User user = permHelper.getUserFromRequest(request);
    if (user != null) {
      // 将session信息设置到本地线程中
      SecuritySession.set(user);
    }

    // 不需要登录自然不需要校验菜单
    if (!isNeedLogin) {
      return true;
    }

    if (user == null) {
      throw new BizException(CommonStatusCode.REDIRECT, "/admin");
    }

    // 需要判断api是不是只能管理员访问
    if (isCheckAdmin && user.getType() != User.TYPE_ADMIN) {
      throw new BizException(CommonStatusCode.UNAUTHORIZED, "您无权进行该操作");
    }

    // 不需要校验菜单权限
    if (!isCheckMenuPerm) {
      return true;
    }

    // 开始校验菜单权限，首先获取请求的uri
    String uri = request.getRequestURI().toString();
    // 去掉contextPath
    if (uri.startsWith(request.getContextPath())) {
      uri = uri.replaceFirst(request.getContextPath(), "");
    }

    // 进入以下逻辑的部分代表需要判断菜单权限
    Role role = roleService.get(user.getRoleId());
    // 获取角色下的菜单
    List<Menu> menuList = menuService.getMenuList(role.getMenuIds());
    for (Menu menu : menuList) {
      if (!StringUtils.isEmpty(menu.getUrlPattern())
          && pathMatcher.match(menu.getUrlPattern(), uri)) {
        return true;
      }
    }

    logger.warn("url: {} will be break.", uri);
    throw new BizException(CommonStatusCode.UNAUTHORIZED, "您无权进行此操作");
  }

  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
      ModelAndView modelAndView) throws Exception {

  }

  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
      Object handler, Exception ex) throws Exception {
    // 请求结束的时候本地线程清空保存的用户信息
    SecuritySession.clearOnOver();
  }
}
